﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Drawing;
using System.IO;
using System.Threading;
using System.Windows.Forms;
using System.Xml;

using VirtualTournaments.MatchProvider;

namespace VirtualTournaments.DesktopMatchViewer
{
	public partial class DesktopMatchViewer : Form
	{
		private XmlDocument sourceDocument;
		private ShowableMatch match;
		private bool firstHalf = true;
		private float currentTime = 0;
		private float timeStep = 0;

		public DesktopMatchViewer()
		{
			string teamName;
			Color teamColor;
			InitializeComponent();
			pictureBoxField.Image = Resources.Images.Field;
			BackgroundImage = Resources.Images.StadiumBackground;
			BackgroundImageLayout = ImageLayout.Stretch;
			buttonPause.Enabled = false;
			buttonResume.Enabled = false;
			buttonStop.Enabled = false;
			groupBoxPlayerLabel.Enabled = false;

			sourceDocument = new XmlDocument();
			try
			{
				sourceDocument.Load(ConfigurationSettings.AppSettings["FilePath"].ToString());

				labelProgramStatusText.ForeColor = Color.Green;
				labelProgramStatusText.Text = "OK";

				match = MatchProvider.MatchProvider.LoadMatch(sourceDocument);

				timeStep = (20 / match.MatchHalfCicles);
				trackBar1.Maximum = Convert.ToInt32(match.MatchHalfCicles);
				trackBar1.Value = 0;
				labelTimeText.Text = ((int)currentTime).ToString();
				foreach (ShowableTeam team in match.getTeamsInMatch())
				{
					teamName = ParseTeamName(team.teamName);
					teamColor = ParseTeamColor(team.teamColor);

					if (team.teamID.Equals("A"))
					{
						labelTeamA.Text = teamName;
						labelTeamA.ForeColor = teamColor;
					}
					else
					{
						labelTeamB.Text = teamName;
						labelTeamB.ForeColor = teamColor;
					}

					foreach (ShowableParticipant participant in team.getParticipants())
					{
						pictureBoxField.Controls.Add(participant);
						participant.setPosition(0);
					}
				}

				pictureBoxField.Controls.Add(match.getMatchBall());
				match.getMatchBall().setPosition(0);

				pictureBoxField.Refresh();
			}
			catch (IOException)
			{
				buttonStart.Enabled = false;
				labelProgramStatusText.ForeColor = Color.Red;
				labelProgramStatusText.Text = "File not found!";
			}
		}

		private Color ParseTeamColor(string xColor)
		{
			switch (xColor)
			{
				case "rojo": return Color.Red;
				case "azul": return Color.Blue;
				case "blanco": return Color.White;
				case "verde": return Color.Green;
				case "celeste": return Color.LightBlue;
				default: return Color.Black;
			}
		}

		// Move participants according to cicles in corresponding half
		private void PlayHalf()
		{
			IsRunningSimulation = true;

			long currentCicles = 0;
			List<ShowableEvent> matchEvents = null;
			if (!firstHalf)
				currentCicles = match.MatchHalfCicles;
			currentTime += timeStep;
			labelTimeText.Invoke(() => labelTimeText.Text = ((int)currentTime).ToString());

			for (int i = 1; i < match.MatchHalfCicles; i++)
			{
				if (!IsRunningSimulation)
					break;
				Thread.Sleep(Int32.Parse(ConfigurationSettings.AppSettings["Delay"]));

				trackBar1.Invoke(() => { if (trackBar1.Value < trackBar1.Maximum) trackBar1.Value++; });
				foreach (Control participant in pictureBoxField.Controls)
					((ShowableParticipant)participant).setPosition(i + (int)currentCicles);
				pictureBoxField.Invoke(() => pictureBoxField.Refresh());
				matchEvents = match.eventsOnCicle(i + currentCicles);
				if (matchEvents != null)
					ProcessEvents(matchEvents);
				currentTime += timeStep;
				labelTimeText.Invoke(() => labelTimeText.Text = ((int)currentTime).ToString());
				groupBoxMatchInfo.Invoke(() => groupBoxMatchInfo.Refresh());
			}

			if (!IsLeaving)
			{
				if (firstHalf)
				{
					MessageBox.Show("First half has finished.", "Half finished");
					labelMatchHalf.Invoke(() => labelMatchHalf.Text = "Second Half");
					buttonStart.Invoke(() => buttonStart.Text = "");//"Begin Second Half");
					trackBar1.Invoke(() => trackBar1.Value = 0);
					foreach (ShowableTeam team in match.getTeamsInMatch())
					{
						team.setParticipantsPosition((int)match.MatchHalfCicles);
					}

					match.getMatchBall().setPosition((int)match.MatchHalfCicles);

					firstHalf = false;
				}
				else
				{
					buttonStart.Invoke(() => buttonStart.Enabled = false);
					MessageBox.Show("Match has finished.", "Second half finished");
				}
			}
		}

		private void buttonStart_Click(object sender, EventArgs e)
		{
			Thread halfThread = new Thread(new ThreadStart(PlayHalf));
			halfThread.Start();
		}

		private void ProcessEvents(List<ShowableEvent> xMatchEvents)
		{
			foreach (ShowableEvent newEvent in xMatchEvents)
			{
				labelEventDescription.Invoke(() => labelEventDescription.Text = newEvent.fullEventDescription);
				labelTeamName.Invoke(() => labelTeamName.Text = match.getTeamName(newEvent.team));
				labelPlayerName.Invoke(() => labelPlayerName.Text = match.getParticipantName(newEvent.team, newEvent.participant - 1));

				switch (newEvent.eventDescription)
				{
					case "gol":
						{
							labelEventDescription.ForeColor = Color.Blue;
							if (newEvent.team.Equals("A"))
								labelTeamAGoals.Invoke(() => labelTeamAGoals.Text = (Convert.ToInt32(labelTeamAGoals.Text) + 1).ToString());
							else
								labelTeamBGoals.Invoke(() => labelTeamBGoals.Text = (Convert.ToInt32(labelTeamBGoals.Text) + 1).ToString());
							MessageBox.Show(labelPlayerName.Text + " scored!!!", "Goal!!!");
							break;
						}
					case "golEnContra":
						{
							labelEventDescription.ForeColor = Color.Red;
							if (newEvent.team.Equals("B"))
								labelTeamAGoals.Invoke(() => labelTeamAGoals.Text = (Convert.ToInt32(labelTeamAGoals.Text) + 1).ToString());
							else
								labelTeamBGoals.Invoke(() => labelTeamBGoals.Text = (Convert.ToInt32(labelTeamBGoals.Text) + 1).ToString());
							MessageBox.Show(labelPlayerName.Text + " scored!!!", "Own Goal!!!");
							break;
						}
					case "amarilla":
						{
							labelEventDescription.Invoke(() => labelEventDescription.ForeColor = Color.Yellow);
							MessageBox.Show(labelPlayerName.Text + " got a yellow card.", "Card");
							break;
						}
					case "roja":
						{
							labelEventDescription.Invoke(() => labelEventDescription.ForeColor = Color.Red);
							RemoveParticipant(newEvent.team, newEvent.participant - 1);
							MessageBox.Show(labelPlayerName.Text + " got a red card. He is out of the game.", "Card");
							break;
						}
					default:
						{
							labelEventDescription.Invoke(() => labelEventDescription.ForeColor = Color.Brown);
							MessageBox.Show(labelPlayerName.Text + " commited a fault.", "Fault");
							break;
						}
				}
			}
		}

		private void RemoveParticipant(string p, int p_2)
		{
			ShowableParticipant participantExpelled = match.getParticipant(p, p_2);
			pictureBoxField.Invoke(() => pictureBoxField.Controls.Remove(participantExpelled));
		}

		private string ParseTeamName(string xTeamBName)
		{
			return xTeamBName.Substring(0, 3).ToUpper();
		}

		private void buttonExit_Click(object sender, EventArgs e)
		{
			IsLeaving = true;
			if (IsRunningSimulation)
				StopSimulation();
			Application.Exit();
		}

		private bool _isLeaving = false;
		private bool IsLeaving
		{
			get { lock (this) { return _isLeaving; } }
			set { lock (this) { _isLeaving = value; } }
		}

		private bool _isRunningSimulation;
		private bool IsRunningSimulation
		{
			get { lock (this) { return _isRunningSimulation; } }
			set { lock (this) { _isRunningSimulation = value; } }
		}
		private void StopSimulation()
		{
			IsRunningSimulation = false;
		}

		private void DesktopMatchViewer_Load(object sender, EventArgs e)
		{

		}
	}
}
